﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using AdminModule.IndexMarkServiceReference;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using AdminModule.UserControls.StructView;

namespace AdminModule.StructEditStratagies
{
    /// <summary>
    /// Стратегия редактирования структуры. Отвечает за изменение содержимого коллекций узлов, установку связей между элементами и установку ID периодов у добавляемых элементов
    /// </summary>
    public abstract class StructEditBaseStrategy
    {
        /// <summary>
        /// Перемещение объекта
        /// </summary>
        /// <param name="obj">Какой объект переносится</param>
        /// <param name="toObject">Куда объект переносится</param>
        public virtual bool Move(DTOBase obj, DTOBase fromObject, DTOBase toObject)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Удаление объекта
        /// </summary>
        /// <param name="obj">Какой объект удаляем</param>
        public virtual bool Delete(DTOBase obj, DTOBase fromObject)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Добавление объекта
        /// </summary>
        /// <param name="obj">Какой объект добавляем</param>
        /// <param name="toObject">Куда добавляем</param>
        public virtual bool Add(DTOBase obj, DTOBase toObject)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Не помещает элемент в коллекцию модифицмрованных объектов, а возвращает копируемый объект с некоторыми измененными атрибутами для копирования
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="toObject"></param>
        /// <returns></returns>
        public virtual DTOBase CopyTo(DTOBase obj, DTOBase toObject, int toIDTerm)
        {
            throw new NotImplementedException();
        }

        public delegate void ObjectChanged(DTOBase obj);
        public event ObjectChanged ObjectChangedEvent;

        private void RaiseEvent(DTOBase obj)
        {
            if (this.ObjectChangedEvent != null)
            {
                this.ObjectChangedEvent(obj);
            }
        }

        protected void SetState(DTOBase obj, StateObject state)
        {
            // Удаленный объект не может быть обновленным
            if (obj.State == StateObject.Deleted && state == StateObject.Updated)
            {
                // Исключения для теста
                //throw new ArgumentException("Удаленный объект не может быть обновленным");
                return;
            }
            // Созданный объект не может быть обновленным
            if (obj.State == StateObject.Created && state == StateObject.Updated)
            {
                // Исключения для теста
                //throw new ArgumentException("Созданный объект не может быть обновленным");
                return;
            }
            // Если пользователь добавил элемент, а затем сразу удалил его, то его незачем передавать на сервер
            if (obj.State == StateObject.Created && state == StateObject.Deleted)
            {
                StructViewBase.changedElements.Remove(obj);
                return;
            }
            
            obj.State = state;
            this.RaiseEvent(obj);
        }

        public virtual void Edit(DTOBase obj)
        {
            SetState(obj, StateObject.Updated);
        }

        public virtual void Replace(DTOBase new_obj, DTOBase old_obj, DTOBase parentObject)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Рекурсивно обходит иерархию градаций и устанавливает каждому элементу в иерархии указанное состояние.
        /// Состояние параметра from так же изменяется
        /// </summary>
        /// <param name="from">Стартовый объект</param>
        /// <param name="state">Состояние, которое нужно установить каждому объекту</param>
        /// <param name="forTypes">Коллекция типов данных, для которых необъходимо установить данное состояние</param>
        protected void SetState(DTOChilds from, StateObject state, List<Type> forTypes)
        {
            SetState(from, state);

            foreach (DTOBase el in from.Childs)
            {
                if (forTypes.Contains(el.GetType()))
                {
                    SetState(el, state);
                }
                if (el is DTOChilds)
                {
                    SetState(el as DTOChilds, state, forTypes);
                }
            }
        }
    }
}
